using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net.NetworkInformation;
using System.Runtime.Remoting.Messaging;
using System.Globalization;
using System.Resources;

namespace HostMonitor
{
    class Checker
    {
        private class CheckHostEventArgs:EventArgs
        {
            private string _hostname;            
            private ListViewItem _item;            

            public string HostName
            {
                get { return _hostname;}
            }           
            
        	public ListViewItem Item
	        {
		        get { return _item;}		       
	        }
	

            public CheckHostEventArgs(string HostName, ListViewItem item)
            {
                _hostname=HostName;
                _item=item;
            }
        }

        private delegate PingReply CheckHost(CheckHostEventArgs e);
        private delegate ListViewItem[] GetCompsDelegate();

        private ListView _list;
        private MainFrm _frm;
        private int AsyncCount = 0;
        private Thread _thread;
        private ResourceManager _rm;

        public Checker(ListView list,MainFrm form)
        {
            _rm = new ResourceManager("HostMonitor.Resources", System.Reflection.Assembly.GetExecutingAssembly());
            _list = list;
            _frm = form;
        }

        public void Start()
        {
            _thread = new Thread(Main);
            _thread.Start();
        }
        

        private void Main()
        {
            try
            {
                while (true)
                {
                    OneLoop();
                    Int64 time = Environment.TickCount + Config.Interval;
                    while (Environment.TickCount < time)
                    {
                        Thread.Sleep(10);
                    }
                }
            }
            catch (ThreadAbortException)
            {
                return;                
            }
        }

        private void OneLoop()
        {
            foreach (ListViewItem item in GetComps())
            {
                HostsData.HostsRow host = (HostsData.HostsRow)item.Tag;

                //elimnate not active hosts
                if (host.HostName == "")
                {
                    continue;
                }
                if (!host.Active)
                {
                    continue;
                }
                HostsData.GroupsRow group = (HostsData.GroupsRow)item.Group.Tag;
                if (!group.Active)
                {
                    continue;
                }

                //now we can check this host
                lock (this)
                {
                    if (AsyncCount < Config.MaxAsyncPings)
                    {
                        AsyncCount++;
                        CheckHost del = new CheckHost(Check);
                        CheckHostEventArgs e = new CheckHostEventArgs(host.HostName, item);
                        del.BeginInvoke(e, new AsyncCallback(CheckCallback), item);
                    }
                }
            }
        }

        private PingReply Check(CheckHostEventArgs e)
        {
            Ping p = new Ping();
            try
            {
                return p.Send(e.HostName, Config.Timeout);
            }
            catch
            {
                return null;
            }
        }

        private void CheckCallback(IAsyncResult asResult)
        {
            if (asResult.IsCompleted)
            {
                if (_frm.InvokeRequired)
                {
                    AsyncCallback del = new AsyncCallback(CheckCallback);
                    _frm.Invoke(del, asResult);
                }
                else
                {
                    try
                    {
                        AsyncResult ar = (AsyncResult)asResult;
                        CheckHost del = (CheckHost)ar.AsyncDelegate;
                        PingReply r = del.EndInvoke(asResult);
                        ListViewItem item = (ListViewItem)ar.AsyncState;
                        if (r != null)
                        {                            
                            switch (r.Status)
                            {
                                case IPStatus.Success:
                                    item.SubItems[1].Text = String.Format("{0}", r.RoundtripTime);
                                    break;
                                default:
                                    item.SubItems[1].Text = r.Status.ToString();
                                    break;
                            }
                        }
                        else
                        {
                            item.SubItems[1].Text = _rm.GetString("CheckerErrorOccured");
                        }
                    }
                    catch
                    {}
                    lock (this)
                    {
                        AsyncCount--;
                    }                    
                }                
            }
        }

        private ListViewItem[] GetComps()
        {
            if (_frm.InvokeRequired)
            {
                GetCompsDelegate d = new GetCompsDelegate(GetComps);
                return (ListViewItem[])_frm.Invoke(d);
            }
            else
            {
                ListViewItem[] result=new ListViewItem[_list.Items.Count];
                _list.Items.CopyTo(result, 0);
                return result;
            }
        }

        public void Stop()
        {
            _thread.Abort();
        }
    }
}
